using System;
using System.Runtime.InteropServices;

namespace Leap
{
	public class Frame : Interface
	{
		private HandleRef swigCPtr;

		public byte[] Serialize
		{
			get
			{
				byte[] array = new byte[SerializeLength];
				SerializeWithArg(array);
				return array;
			}
		}

		public long Id => LeapPINVOKE.Frame_Id_get(swigCPtr);

		public long Timestamp => LeapPINVOKE.Frame_Timestamp_get(swigCPtr);

		public float CurrentFramesPerSecond => LeapPINVOKE.Frame_CurrentFramesPerSecond_get(swigCPtr);

		public PointableList Pointables
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Frame_Pointables_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new PointableList(intPtr, true);
			}
		}

		public FingerList Fingers
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Frame_Fingers_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new FingerList(intPtr, true);
			}
		}

		public ToolList Tools
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Frame_Tools_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new ToolList(intPtr, true);
			}
		}

		public HandList Hands
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Frame_Hands_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new HandList(intPtr, true);
			}
		}

		public ImageList Images
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Frame_Images_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new ImageList(intPtr, true);
			}
		}

		public bool IsValid => LeapPINVOKE.Frame_IsValid_get(swigCPtr);

		public InteractionBox InteractionBox
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Frame_InteractionBox_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new InteractionBox(intPtr, true);
			}
		}

		public int SerializeLength => LeapPINVOKE.Frame_SerializeLength_get(swigCPtr);

		public TrackedQuad TrackedQuad
		{
			get
			{
				IntPtr intPtr = LeapPINVOKE.Frame_TrackedQuad_get(swigCPtr);
				return (intPtr == IntPtr.Zero) ? null : new TrackedQuad(intPtr, true);
			}
		}

		public static Frame Invalid => new Frame(LeapPINVOKE.Frame_Invalid_get(), false);

		public Frame(IntPtr cPtr, bool cMemoryOwn)
			: base(LeapPINVOKE.Frame_SWIGUpcast(cPtr), cMemoryOwn)
		{
			swigCPtr = new HandleRef(this, cPtr);
		}

		public static HandleRef getCPtr(Frame obj)
		{
			return obj?.swigCPtr ?? new HandleRef(null, IntPtr.Zero);
		}

		~Frame()
		{
			Dispose();
		}

		public override void Dispose()
		{
			lock (this)
			{
				if (swigCPtr.Handle != IntPtr.Zero)
				{
					if (base.swigCMemOwn)
					{
						base.swigCMemOwn = false;
						LeapPINVOKE.delete_Frame(swigCPtr);
					}
					swigCPtr = new HandleRef(null, IntPtr.Zero);
				}
				GC.SuppressFinalize(this);
				base.Dispose();
			}
		}

		public void Deserialize(byte[] arg)
		{
			DeserializeWithLength(arg, arg.Length);
		}

		public Frame()
			: this(LeapPINVOKE.new_Frame(), true)
		{
		}

		public Hand Hand(int id)
		{
			return new Hand(LeapPINVOKE.Frame_Hand(swigCPtr, id), true);
		}

		public Pointable Pointable(int id)
		{
			return new Pointable(LeapPINVOKE.Frame_Pointable(swigCPtr, id), true);
		}

		public Finger Finger(int id)
		{
			return new Finger(LeapPINVOKE.Frame_Finger(swigCPtr, id), true);
		}

		public Tool Tool(int id)
		{
			return new Tool(LeapPINVOKE.Frame_Tool(swigCPtr, id), true);
		}

		public Gesture Gesture(int id)
		{
			return new Gesture(LeapPINVOKE.Frame_Gesture(swigCPtr, id), true);
		}

		public GestureList Gestures()
		{
			return new GestureList(LeapPINVOKE.Frame_Gestures__SWIG_0(swigCPtr), true);
		}

		public GestureList Gestures(Frame sinceFrame)
		{
			GestureList result = new GestureList(LeapPINVOKE.Frame_Gestures__SWIG_1(swigCPtr, getCPtr(sinceFrame)), true);
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public Vector Translation(Frame sinceFrame)
		{
			Vector result = new Vector(LeapPINVOKE.Frame_Translation(swigCPtr, getCPtr(sinceFrame)), true);
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public float TranslationProbability(Frame sinceFrame)
		{
			float result = LeapPINVOKE.Frame_TranslationProbability(swigCPtr, getCPtr(sinceFrame));
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public Vector RotationAxis(Frame sinceFrame)
		{
			Vector result = new Vector(LeapPINVOKE.Frame_RotationAxis(swigCPtr, getCPtr(sinceFrame)), true);
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public float RotationAngle(Frame sinceFrame)
		{
			float result = LeapPINVOKE.Frame_RotationAngle__SWIG_0(swigCPtr, getCPtr(sinceFrame));
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public float RotationAngle(Frame sinceFrame, Vector axis)
		{
			float result = LeapPINVOKE.Frame_RotationAngle__SWIG_1(swigCPtr, getCPtr(sinceFrame), Vector.getCPtr(axis));
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public Matrix RotationMatrix(Frame sinceFrame)
		{
			Matrix result = new Matrix(LeapPINVOKE.Frame_RotationMatrix(swigCPtr, getCPtr(sinceFrame)), true);
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public float RotationProbability(Frame sinceFrame)
		{
			float result = LeapPINVOKE.Frame_RotationProbability(swigCPtr, getCPtr(sinceFrame));
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public float ScaleFactor(Frame sinceFrame)
		{
			float result = LeapPINVOKE.Frame_ScaleFactor(swigCPtr, getCPtr(sinceFrame));
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public float ScaleProbability(Frame sinceFrame)
		{
			float result = LeapPINVOKE.Frame_ScaleProbability(swigCPtr, getCPtr(sinceFrame));
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public bool Equals(Frame arg0)
		{
			bool result = LeapPINVOKE.Frame_Equals(swigCPtr, getCPtr(arg0));
			if (LeapPINVOKE.SWIGPendingException.Pending)
			{
				throw LeapPINVOKE.SWIGPendingException.Retrieve();
			}
			return result;
		}

		public void SerializeWithArg(byte[] ptr)
		{
			LeapPINVOKE.Frame_SerializeWithArg(swigCPtr, ptr);
		}

		public void DeserializeWithLength(byte[] ptr, int length)
		{
			LeapPINVOKE.Frame_DeserializeWithLength(swigCPtr, ptr, length);
		}

		public override string ToString()
		{
			return LeapPINVOKE.Frame_ToString(swigCPtr);
		}
	}
}
